import { isArray } from 'util';

/**
 * @author leihfei
 * @date 2019-04-01
 * @description 配合后台fastjson转换工具类
 */
export class FastJsonFormatter {

  static formatter(o: Object): any {
    if (null === o) {
      return o;
    }
    return this._format(o, o, null, null);
  }

  private static _format(root: any, t: any, c: Object, p) {
    if (this.isObject(t)) {
      if (t.hasOwnProperty('$ref')) {
        const path = t['$ref'];
        if (path.startsWith('$.')) {
          c[p] = this._getJsonValue(root, path.substring(2));
        }
        return;
      }
      for (const f in t) {
        if (t.hasOwnProperty(f)) {
          this._format(root, t[f], t, f);
        }
      }
    } else if (isArray(t)) {
      for (const v in t) {
        if (t.hasOwnProperty(v)) {
          this._format(root, t[v], t, v);
        }
      }
    }
    return root;
  }


  private static _getJsonValue(root: any, s: string) {
    let t = this.deepCloneByJson(root);
    const split = s.split('.');

    for (let i = 0 ; i < split.length ; i++) {
      if (split[i].endsWith(']')) {
        const ar = split[i].split('[');
        t = t[ar[0]][Number.parseInt(ar[1].substring(0, ar[1].length - 1))];
      } else {
        t = t[split[i]];
      }
    }
    return t;
  }

  private static isObject(o) {
    return typeof o === 'object' && Object.prototype.toString.call(o) === '[object Object]';
  }

  private static deepClone(obj) {

    // return value is input is not an Object or Array.
    if (typeof (obj) !== 'object' || obj === null) {
      return obj;
    }

    let clone;

    if (isArray(obj)) {
      clone = obj.slice();  // unlink Array reference.
    } else {
      clone = Object.assign({}, obj); // Unlink Object reference.
    }

    const keys = Object.keys(clone);

    for (let i = 0 ; i < keys.length ; i++) {
      clone[keys[i]] = this.deepClone(clone[keys[i]]); // recursively unlink reference to nested objects.
    }
    return clone; // return unlinked clone.
  }

  private static deepCloneByJson(root: any) {
    const json = JSON.stringify(root);
    return JSON.parse(json);
  }
}
